第37章 二维和多维数组
数组是存储相同类型数据的集合,一维数组是线性排列的数据集合,而二维和多维数组则是在一维数组的基础上扩展而来,用于表示更复杂的数据结构(如矩阵、表格等)。
37.1 二维数组
二维数组可以理解为"数组的数组",它由若干个一维数组组成,每个一维数组称为"行",行中的元素称为"列"。二维数组常用于表示表格、矩阵等具有行和列结构的数据。
37.1.1 二维数组的定义
二维数组的定义语法如下:
数据类型 数组名[行数][列数];
- 数据类型:数组中所有元素的数据类型(如int、double等)。
- 数组名:遵循标识符命名规则。
- 行数:表示二维数组包含的一维数组(行)的数量。
- 列数:表示每个一维数组中包含的元素数量。
示例:
int matrix[3][4]; // 3行4列int二维数组
double table[2][3]; // 2行3列double二维数组
37.1.2 二维数组的初始化
- 按行初始化
int arr1[2][3]={
{1, 2, 3},
{4, 5, 6}
};
- 顺序平铺初始化,编译器自动分行
int arr2[2][3]={1, 2, 3, 4, 5, 6};
- 部分初始化,未赋值元素自动置0
int arr3[3][3]={
{1},
{2, 3},
{4, 5, 6}
};
// 填充后:
// 1 0 0
// 2 3 0
// 4 5 6
- 省略行数,列数不可省略
int arr4[][3]={1,2,3,4,5,6}; // 自动识别2行
37.1.3 二维数组元素访问
语法:数组名[行下标][列下标],下标从0开始
int arr[2][3]={{1,2,3},{4,5,6}};
cout << arr[0][0] << endl; // 输出1
cout << arr[1][2] << endl; // 输出6
arr[0][1] = 10; // 修改元素值
37.1.4 二维数组遍历
嵌套循环,外层控制行,内层控制列
int matrix[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
for(int i=0;i<3;i++){ // 遍历每一行
for(int j=0;j<4;j++){ // 遍历当前行每一列
cout << matrix[i][j] << " ";
}
cout << endl;
}
37.1.5 二维数组内存存储
C/C++二维数组行优先连续存储,先存完整第0行,再第1行,以此类推。
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p = &arr[0][0];
for(int i=0;i<6;i++){
cout << *(p+i) << " ";
}
// 输出:1 2 3 4 5 6
37.2 多维数组
多维数组是二维数组的扩展,三维及以上数组逻辑一致,三维常用作立方体数据。
37.2.1 三维数组定义
数据类型 数组名[维度1][维度2][维度3];
示例:
int cube[2][3][4]; // 2页3行4列三维数组
37.2.2 三维数组初始化
int cube[2][2][2]={
{{1,2},{3,4}},
{{5,6},{7,8}}
};
// 可省略第一维
int cube[][2][2]={{1,2},{3,4},{5,6},{7,8}};
37.2.3 三维数组访问与遍历
int cube[2][2][2]={{{1,2},{3,4}},{{5,6},{7,8}}};
cout << cube[0][1][0]; // 输出3
// 三层循环遍历
for(int page=0;page<2;page++){
cout << "第" << page << "页:" << endl;
for(int row=0;row<2;row++){
for(int col=0;col<2;col++){
cout << cube[page][row][col] << " ";
}
cout << endl;
}
}
37.2.4 多维数组存储
全部遵循行优先连续内存排布。
37.3 多维数组作为函数参数
传递多维数组时,第一维可省略,其余维度必须写明,编译器依靠列数计算内存偏移。
37.1 二维数组传参
两种等价写法:
// 写法1
void printMatrix(int matrix[][4], int rows){
for(int i=0;i<rows;i++){
for(int j=0;j<4;j++) cout << matrix[i][j] << " ";
cout << endl;
}
}
// 写法2(行指针形式)
void printMatrix(int (*matrix)[4], int rows){}
// 调用
int m[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printMatrix(m, 3);
37.2 三维数组传参
void printCube(int cube[][2][2], int pages){
// ...
}
37.4 动态二维数组(运行时确定行列)
使用指针+new实现,行地址不连续,需分层释放内存。
#include <iostream>
using namespace std;
int main(){
int rows = 3, cols = 4;
// 1. 分配行指针数组
int** dynamicMat = new int*[rows];
// 2. 逐行分配列空间
for(int i=0;i<rows;i++){
dynamicMat[i] = new int[cols];
}
// 赋值
int num = 1;
for(int i=0;i<rows;i++)
for(int j=0;j<cols;j++)
dynamicMat[i] = num++;
// 打印
for(int i=0;i<rows;i++){
for(int j=0;j<cols;cout << dynamicMat[i][j] << " ";
cout << endl;
}
// 释放内存:先释放每行,再释放行指针
for(int i=0;i<rows;i++) delete[] dynamicMat[i];
delete[] dynamicMat;
dynamicMat = nullptr;
return 0;
}
37.5 二维数组与行指针
int arr[2][3];中数组名arr是指向长度为3的一维数组的行指针,类型为int(*)[3]。
int arr[2][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = arr;
cout << *(*p) << endl; // arr[0][0] = 1
p++;
cout << *(*p) << endl; // arr[1][0] = 4
37.6 注意事项
- 下标越界:行列下标必须小于定义长度,越界产生未定义行为;
- 初始化每行元素不能超过定义列数;
- 函数传参仅能省略第一维;
- 动态二维数组释放顺序:先释放每行,再释放行指针;
- 静态二维数组内存连续,动态二维数组各行内存分散。